#include "workflows.hh"
#include "rule.hh"

#include <string>
#include <memory>
#include <vector>
#include <iostream>
#include <algorithm>

Workflow::Workflow(const std::string& line) : 
    _name{},
    _rules{}
{
    // px{a<2006:qkq,m>2090:A,rfg}
    std::size_t leftPos {line.find('{')};
    this->_name = line.substr(0, leftPos);

    std::size_t begin {leftPos + 1};
    std::size_t end {begin + 1};
    std::size_t maxIndx {line.size() - 2};

    while (begin <= maxIndx)
    {
        // Find ','
        if (line[end] != ',' && line[end] != '}')
        {
            end += 1;
            continue;
        }

        // line[end] is ','
        // line[begin..end) is rule stirng
        this->_rules.emplace_back(makeRule(line.substr(begin, end - begin)));

        // Update begin and end
        begin = end + 1;
        end = begin + 1;
    }
}

void Workflow::print() const
{
    std::cout << this->_name << std::endl;
    std::for_each(this->_rules.cbegin(), this->_rules.cend(), [](const std::unique_ptr<Rule>& rule){
        rule->print();
    });
    std::cout << std::endl;
}   

auto Workflow::result(Rating* rating) const -> std::tuple<WorkflowResult, std::string>
{
    for (const std::unique_ptr<Rule>& rule : this->_rules)
    {
        auto[result, workflow] {rule->result(rating)};
        switch (result)
        {
            case RuleResult::Accept: return std::make_tuple(WorkflowResult::Accept, "");
            case RuleResult::Reject: return std::make_tuple(WorkflowResult::Reject, "");
            case RuleResult::Jump: return std::make_tuple(WorkflowResult::Jump, std::move(workflow));
            case RuleResult::Next: continue;
        }
    }
    return std::make_tuple(WorkflowResult::Reject, "");
}